package com.jsits.v2x.compute.service.impl;

import com.jsits.v2x.common.dto.ControlDto;
import com.jsits.v2x.common.enums.NumberColor;
import com.jsits.v2x.common.enums.DevicePosition;
import com.jsits.v2x.common.enums.TextContent;
import com.jsits.v2x.common.util.HttpUtil;
import com.jsits.v2x.compute.config.DataConfig;
import com.jsits.v2x.compute.config.ComputeConfig;
import com.jsits.v2x.compute.dto.MainRoadStatusDto;
import com.jsits.v2x.compute.service.ComputeService;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class ComputeServiceImpl implements ComputeService {

    @Autowired
    private DataConfig dataConfig;

    @Autowired
    private ComputeConfig computeConfig;

    // 行人在线状态
    protected static Boolean sidewalkStatus = false;

    // 上传数据timeKey
    private static Integer timeKey = getTimeKey();

    // 上传数据timeKey
    private static Integer dateKey = getDateKey();

    /**
     * 更新主路led屏上显示的内容
     * @param controlDto 主路内容缓存
     * @param speed 车速
     * @param sidewalkStatus 支路上是否有行人
     */
    private void updateMainRoad(ControlDto controlDto, Integer speed, Boolean sidewalkStatus) {
        if (speed > computeConfig.getMaxSpeed()) {
            // 超速
            if (sidewalkStatus) {
                //有人
                controlDto.setTextContent(TextContent.TEXT_CONTENT_MAIN_OVER_MAN);
            } else {
                //没人
                controlDto.setTextContent(TextContent.TEXT_CONTENT_MAIN_OVER_NOMAN);
            }
            controlDto.setNumberColor(NumberColor.RED);
        } else {
            // 未超速
            if (sidewalkStatus) {
                //有人
                controlDto.setTextContent(TextContent.TEXT_CONTENT_MAIN_UNDER_MAN);
            } else {
                //无人
                controlDto.setTextContent(TextContent.TEXT_CONTENT_MAIN_UNDER_NOMAN);
            }
        }
    }

    /**
     * 更新支路屏上显示的内容
     * @param controlDto 支路内容缓存
     * @param rightSpeed 右边主路方向的车速
     * @param leftSpeed 左边主路方向的车速
     * @param sidewalkStatus 支路上是否有行人
     */
    private void updateSubRoad(ControlDto controlDto, Integer rightSpeed, Integer leftSpeed, Boolean sidewalkStatus) {
        if(sidewalkStatus) {
            // 有行人通过
            if(rightSpeed >0 && leftSpeed > 0) {
                // 看看两边
                controlDto.setTextContent(TextContent.TEXT_CONTENT_SUB_SIDES);
            } else if(rightSpeed > 0) {
                // 看看右边
                controlDto.setTextContent(TextContent.TEXT_CONTENT_SUB_RIGHT);
            } else if(leftSpeed > 0) {
                // 看看左边
                controlDto.setTextContent(TextContent.TEXT_CONTENT_SUB_LEFT);
            } else {
                // 谨慎通过
                controlDto.setTextContent(TextContent.TEXT_CONTENT_SUB_NONE);
            }
        } else {
            //没有行人通过 谨慎通过
            controlDto.setTextContent(TextContent.TEXT_CONTENT_SUB_NONE);
        }
    }

    /**
     * 根据路口各个方向探测的速度数据，计算每个屏幕显示的内容
     */
    @Override
    public void updateAllRoad() {
        // 支路是否有行人
        Boolean sidewalkStatus = dataConfig.getSub1Speed() > 0 || dataConfig.getSub2Speed() > 0;

        //主路方向1
        Integer main1Speed = dataConfig.getMain1Speed();
        ControlDto controlDto1 = dataConfig.getControlDtoMain1();
        controlDto1.setTextContent(TextContent.TEXT_CONTENT_MAIN_UNDER_NOMAN);
        controlDto1.setDevicePosition(DevicePosition.DEVICE_POSITION_MAIN_1);
        controlDto1.setNumberColor(NumberColor.GREEN);
        controlDto1.setNumberContent(main1Speed);
        updateMainRoad(controlDto1, main1Speed, sidewalkStatus);

        //主路方向2
        Integer main2Speed = dataConfig.getMain2Speed();
        ControlDto controlDto2 = dataConfig.getControlDtoMain2();
        controlDto2.setTextContent(TextContent.TEXT_CONTENT_MAIN_UNDER_NOMAN);
        controlDto2.setDevicePosition(DevicePosition.DEVICE_POSITION_MAIN_2);
        controlDto2.setNumberColor(NumberColor.GREEN);
        controlDto2.setNumberContent(main2Speed);
        updateMainRoad(controlDto2, main2Speed, sidewalkStatus);

        //支路方向1, 主路方向1在右边，主路方向2在左边
        Integer sub1Speed = dataConfig.getSub1Speed();
        sidewalkStatus = sub1Speed > 0;
        ControlDto subControlDto1 = dataConfig.getControlDtoSub1();
        subControlDto1.setDevicePosition(DevicePosition.DEVICE_POSITION_SUB_1);
        subControlDto1.setNumberColor(NumberColor.GREEN);
        subControlDto1.setNumberContent(sub1Speed);
        updateSubRoad(subControlDto1, main1Speed, main2Speed, sidewalkStatus);

        //支路方向2， 主路方向1在左边，主路方向2在右边
        Integer sub2Speed = dataConfig.getSub1Speed();
        sidewalkStatus = dataConfig.getSub2Speed() > 0;
        ControlDto subControlDto2 = dataConfig.getControlDtoSub2();
        subControlDto2.setDevicePosition(DevicePosition.DEVICE_POSITION_SUB_2);
        subControlDto2.setNumberColor(NumberColor.GREEN);
        subControlDto2.setNumberContent(sub2Speed);
        updateSubRoad(subControlDto2, main2Speed, main1Speed, sidewalkStatus);

        //更新缓存的上次速度
        dataConfig.setLastLastMain1Speed(dataConfig.getLastMain1Speed());
        dataConfig.setLastLastMain2Speed(dataConfig.getLastMain2Speed());
        dataConfig.setLastLastSub1Speed(dataConfig.getLastSub1Speed());
        dataConfig.setLastLastSub2Speed(dataConfig.getLastSub2Speed());
        dataConfig.setLastMain1Speed(dataConfig.getMain1Speed());
        dataConfig.setLastMain2Speed(dataConfig.getMain2Speed());
        dataConfig.setLastSub1Speed(dataConfig.getSub1Speed());
        dataConfig.setLastSub2Speed(dataConfig.getSub2Speed());
    }

    /**
     * 上传路口状态
     */
    @Override
    public void uploadDataService() {
        Integer maxSpeed = computeConfig.getMaxSpeed();

        Date nowDate = new Date();

        Integer nowTime = getTimeKey();
        // 如果在同一分钟内就继续收集数据
        if (nowTime.equals(timeKey)) {
            // 不同方向分开统计

            MainRoadStatusDto fir = dataConfig.getMainRoadStatusDto_1();
            Integer firSpeed = dataConfig.getMain1Speed();
            // 如果超速了
            if (firSpeed > maxSpeed) {
                // 最高超速速度比对
                if (firSpeed > fir.getHighestSpeed()) {
                    fir.setHighestSpeed(firSpeed);
                }

                // TODO 从缓存map中拿出上一次超速发生时间
                Date speedDate = dataConfig.getMain1OverSpeedTime();
                if (speedDate != null) {
                    // 与上一秒超速时间对比，大于等于10s就算有效超速
                    if ((nowDate.getTime() - speedDate.getTime()) >= 10 * 1000) {
                        fir.setSpeedingCount(fir.getSpeedingCount() + 1);
                        dataConfig.setMain1OverSpeedTime(nowDate);
                    }
                } else {
                    // 如果是第一次就直接记录次数并记录时间
                    fir.setSpeedingCount(fir.getSpeedingCount() + 1);
                    dataConfig.setMain1OverSpeedTime(nowDate);
                }

                // 计算平均超速速度  求每秒平均值
                if (!fir.getSpeedingCount().equals(0)) {
                    fir.setAvgSpeeding((fir.getAvgSpeeding() * (fir.getSpeedingCount() - 1) + firSpeed) / fir.getSpeedingCount());
                } else {
                    fir.setAvgSpeeding(0);
                }
            }

            // 如果这次与上一次行人状态不一致
            if (sidewalkStatus != fir.isLastSidewalk()) {
                // 这一次是没人 就结束过街并记录下这次过街
                if (!sidewalkStatus) {
                    // 更新过街次数
                    fir.setCrossCount(fir.getCrossCount() + 1);
                }
                // 更新状态
                fir.setLastSidewalk(sidewalkStatus);
            } else {
                // 如果两次状态一致
                // 并且都是有人状态
                if (sidewalkStatus) {
                    // 更新过街时间
                    fir.setCrossTime(fir.getCrossTime() + 1);
                    // 更新过街平均速度
                    if (!fir.getCrossTime().equals(0)) {
                        fir.setAvgWalkingSpeed((fir.getAvgWalkingSpeed() * (fir.getCrossTime() - 1) + firSpeed) / fir.getCrossTime());
                    } else {
                        fir.setAvgWalkingSpeed(0);
                    }
                }
            }

            MainRoadStatusDto sec = dataConfig.getMainRoadStatusDto_2();
            Integer secSpeed = dataConfig.getMain2Speed();
            // 如果超速了
            if (secSpeed > maxSpeed) {
                // 最高超速速度比对
                if (secSpeed > sec.getHighestSpeed()) {
                    sec.setHighestSpeed(secSpeed);
                }

                // TODO 从缓存map中拿出上一次超速发生时间
                Date speedDate = dataConfig.getMain2OverSpeedTime();
                if (speedDate != null) {
                    // 与上一秒超速时间对比，大于等于10s就算有效超速
                    if ((nowDate.getTime() - speedDate.getTime()) >= 10 * 1000) {
                        sec.setSpeedingCount(sec.getSpeedingCount() + 1);
                        dataConfig.setMain2OverSpeedTime(nowDate);
                    }
                } else {
                    // 如果是第一次就直接记录次数并记录时间
                    sec.setSpeedingCount(sec.getSpeedingCount() + 1);
                    dataConfig.setMain2OverSpeedTime(nowDate);
                }

                // 计算平均超速速度  求每秒平均值
                if (!sec.getSpeedingCount().equals(0)) {
                    sec.setAvgSpeeding((sec.getAvgSpeeding() * (sec.getSpeedingCount() - 1) + secSpeed) / sec.getSpeedingCount());
                } else {
                    sec.setAvgSpeeding(0);
                }
            }

            // 如果这次与上一次行人状态不一致
            if (sidewalkStatus != sec.isLastSidewalk()) {
                // 这一次是没人 就记录下这次过街
                if (!sidewalkStatus) {
                    // 更新过街次数
                    sec.setCrossCount(sec.getCrossCount() + 1);
                }
                // 更新状态
                sec.setLastSidewalk(sidewalkStatus);
            } else {
                // 如果两次状态一致
                // 并且都是有人状态
                if (sidewalkStatus) {
                    // 更新过街时间
                    sec.setCrossTime(sec.getCrossTime() + 1);
                    // 更新过街平均速度
                    if (!sec.getCrossTime().equals(0)) {
                        sec.setAvgWalkingSpeed((sec.getAvgWalkingSpeed() * (sec.getCrossTime() - 1) + secSpeed) / sec.getCrossTime());
                    } else {
                        sec.setAvgWalkingSpeed(0);
                    }
                }
            }
        } else {
            // 不在同一分钟就推送之前的数据
            MainRoadStatusDto fir = dataConfig.getMainRoadStatusDto_1();
            fir.setDirection(computeConfig.getMainDirection1());
            fir.setDateKey(dateKey);
            fir.setTimeKey(timeKey);
            log.debug("--------------------------- sendPost start ---------------------------");
            HttpUtil.sendPost(computeConfig.getPostUrl(), conventPostParam(fir));
            log.debug("---------------------------sendPost end ---------------------------");
            dataConfig.setMainRoadStatusDto_1(new MainRoadStatusDto());

            MainRoadStatusDto sec = dataConfig.getMainRoadStatusDto_2();
            sec.setDirection(computeConfig.getMainDirection2());
            sec.setDateKey(dateKey);
            sec.setTimeKey(timeKey);
            log.debug("--------------------------- sendPost start ---------------------------");
            HttpUtil.sendPost(computeConfig.getPostUrl(), conventPostParam(sec));
            log.debug("--------------------------- sendPost end ---------------------------");
            dataConfig.setMainRoadStatusDto_2(new MainRoadStatusDto());

            // 更新时间
            timeKey = nowTime;
            dateKey = getDateKey();
            // TODO
            dataConfig.setMain1OverSpeedTime(null);
            dataConfig.setMain2OverSpeedTime(null);
        }
    }

    private String conventPostParam(MainRoadStatusDto temp) {
        StringBuffer sb = new StringBuffer();
        sb.append("pointId=" + computeConfig.getPointId().toString());
        sb.append("&direction=" + temp.getDirection().toString());
        sb.append("&highestSpeed=" + temp.getHighestSpeed().toString());
        sb.append("&avgSpeeding=" + temp.getAvgSpeeding().toString());
        sb.append("&avgWalkingSpeed=" + temp.getAvgWalkingSpeed().toString());
        sb.append("&speedingCount=" + temp.getSpeedingCount().toString());
        sb.append("&crossCount=" + temp.getCrossCount().toString());
        sb.append("&crossTime=" + temp.getCrossTime().toString());
        sb.append("&dateKey=" + temp.getDateKey().toString());
        sb.append("&timeKey=" + temp.getTimeKey().toString());
        return sb.toString();
    }

    /**
     * 获取当前时间分钟数
     * @return
     */
    private static Integer getTimeKey() {
        Integer result = 0;

        // 获取当前小时数
        Integer hour = LocalDateTime.now().getHourOfDay();
        // 获取当前分钟数
        Integer minute = LocalDateTime.now().getMinuteOfHour();

        result = hour * 100 + minute;

        return result;
    }

    /**
     * 获取当前日期年月日8位整数
     * @return
     */
    private static Integer getDateKey() {
        Integer result = 0;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        result = Integer.valueOf(sdf.format(new Date()));

        return result;
    }

}
